package util;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;

import mill.*;
import mill.components.*;
import mill.measurePoints.*;

public class Controller implements Observer, TreeSelectionListener, ActionListener, ListSelectionListener {

	private Model m_model = null;
	private GUI frame = null;

	private MillPark m_selectedPark = null;

	private MillPark m_selectedParkForConfig = null;
	private IMill m_selectedMillForConfig = null;
	private MillComponent m_selectMillComponentForConfig = null;
	private MeasurePoint m_selectedMeasurePointForConfig = null;

	private int m_selectedIndex = -1;

	public Controller(Model model) {
		m_model = model;
		frame = new GUI();

		updateParkList();
		addActionListeners();

		try {
			frame.getCbMillParks().setSelectedIndex(0);
		} catch (Exception e) {

		}


		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);

		frame.getBtnPauseResume().setEnabled(false);
		frame.getBtnStartStop().setEnabled(false);

	}

	private void addActionListeners()
	{
		//Config tree listener connected
		frame.getJConfigTree().getSelectionModel().addTreeSelectionListener(this);

		//Row selected
		frame.getTblMills().getSelectionModel().addListSelectionListener(this);

		frame.addWindowListener(new java.awt.event.WindowAdapter() {
			public void windowClosing(java.awt.event.WindowEvent e) {
				try {
					DatabaseManager.Instance.disconnect();
				} catch (Exception e1) {

				}
				m_model.serializeMillParks();
			}
		});


		frame.getJTabbedPane().addChangeListener(new javax.swing.event.ChangeListener() {
			public void stateChanged(javax.swing.event.ChangeEvent e) {
				int tabIndex = frame.getJTabbedPane().getSelectedIndex();

				switch (tabIndex) {
				case 0:
					addObserverToMill();
					removeTreeListener();
					break;
				case 1:
					removeObserverToMill();
					addTreeListener();
					updateConfigTree();
					break;
				case 2:
					removeObserverToMill();
					removeTreeListener();
					updateLogView();
					break;

				default:
					break;
				}

			}
		});


		frame.getJListOfLogs().addListSelectionListener(new javax.swing.event.ListSelectionListener() {
			public void valueChanged(javax.swing.event.ListSelectionEvent e) {

				LogConfiguration logconf = ((LogConfiguration)frame.getJListOfLogs().getSelectedValue());
				if(logconf != null){
					String filename = logconf.get_filename();
					frame.getTblLogView().setModel(m_model.get_TableModelForLog(filename));
				}

			}
		});


		//Button Start/Stop handler
		frame.getBtnStartStop().addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				IMill mill = m_selectedPark.findMill(Integer.parseInt((frame.getTblMills().getValueAt(m_selectedIndex, 0).toString())));

				if(mill.getStatus() == ProductionStatus.Start)
					mill.setStatus(ProductionStatus.Stop);
				else
					mill.setStatus(ProductionStatus.Start);

				updateMainMillTable();
			}

		});

		//Button Pause/Resume handler
		frame.getBtnPauseResume().addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				IMill mill = m_selectedPark.findMill(Integer.parseInt((frame.getTblMills().getValueAt(m_selectedIndex, 0).toString())));

				if(mill.getStatus() == ProductionStatus.Pause)
					mill.setStatus(ProductionStatus.Start);
				else
					mill.setStatus(ProductionStatus.Pause);

				updateMainMillTable();
			}

		});
	}

	private void updateParkList()
	{
		frame.getCbMillParks().removeActionListener(this);
		frame.getCbMillParks().removeAllItems();		

		for(MillPark mp : m_model.get_MillParks())
		{
			frame.getCbMillParks().addItem(mp);
		}
		frame.getCbMillParks().addActionListener(this);

	}

	private void updateConfigTree()
	{
		frame.getJConfigTree().setModel(new DefaultTreeModel(m_model.get_TreeModel()));
	}

	private void updateMainMillTable()
	{
		MillPark m = (MillPark)frame.getCbMillParks().getSelectedItem();	
		frame.getTblMills().setModel(m_model.get_TableModel(m_model.findMillParkIndex(m)));
	}

	private void updateLogView()
	{
		frame.getJListOfLogs().setModel(m_model.get_ListOfLogModel());
	}



	private void updateButtons(){

		IMill mill = m_selectedPark.findMill(Integer.parseInt((frame.getTblMills().getValueAt(m_selectedIndex, 0).toString())));

		switch (mill.getStatus()) {
		case Start:
			setBtnStart(false);
			setBtnPause(true);
			frame.getBtnStartStop().setEnabled(true);
			frame.getBtnPauseResume().setEnabled(true);
			break;
		case Stop:
			setBtnStart(true);
			frame.getBtnStartStop().setEnabled(true);
			frame.getBtnPauseResume().setEnabled(false);
			break;
		case Pause:
			setBtnStart(false);
			setBtnPause(false);
			frame.getBtnStartStop().setEnabled(true);
			frame.getBtnPauseResume().setEnabled(true);
			break;

		default:
			break;
		}

	}

	private void setBtnStart(boolean isStart)
	{
		if(isStart)
			frame.getBtnStartStop().setText("Start");
		else
			frame.getBtnStartStop().setText("Stop");
	}

	private void setBtnPause(boolean isPause)
	{
		if(isPause)
			frame.getBtnPauseResume().setText("Pause");
		else
			frame.getBtnPauseResume().setText("Resume");
	}

	private void addObserverToMill()
	{
		if(m_selectedPark!=null)
			m_selectedPark.addObserver(this);

		frame.getTblMills().getSelectionModel().addListSelectionListener(this);
	}

	private void removeObserverToMill()
	{
		if(m_selectedPark!=null)
			m_selectedPark.deleteObservers();

		frame.getTblMills().getSelectionModel().removeListSelectionListener(this);
	}

	private void addTreeListener()
	{
		frame.getJConfigTree().getSelectionModel().addTreeSelectionListener(this);
	}

	private void removeTreeListener()
	{
		frame.getJConfigTree().getSelectionModel().removeTreeSelectionListener(this);
	}


	@Override
	public void update(Observable arg0, Object arg1) {
		updateMainMillTable();

	}

	//TreeView eventHandler
	@Override
	public void valueChanged(TreeSelectionEvent arg0) {
		frame.getConfigOption().removeAll();
		frame.getConfigOption().repaint();

		DefaultMutableTreeNode node = (DefaultMutableTreeNode)
		frame.getJConfigTree().getLastSelectedPathComponent();
		if (node == null) return;

		Object nodeInfo = node.getUserObject();

		if(nodeInfo instanceof MillPark)
		{

			m_selectedParkForConfig = (MillPark)nodeInfo;
			edit_millparkEditor();
		}

		if(nodeInfo instanceof IMill)
		{
			m_selectedParkForConfig = (MillPark)((DefaultMutableTreeNode)node.getParent()).getUserObject();
			m_selectedMillForConfig = (IMill)nodeInfo;
			edit_millEditor();
		}

		if(nodeInfo instanceof MillComponent)
		{
			TreeNode nodeComponentContainer = node.getParent();
			DefaultMutableTreeNode nodeMill = (DefaultMutableTreeNode)nodeComponentContainer.getParent();
			DefaultMutableTreeNode nodeMillPark = (DefaultMutableTreeNode)nodeMill.getParent();

			m_selectedParkForConfig = (MillPark)nodeMillPark.getUserObject();
			m_selectedMillForConfig = (IMill)nodeMill.getUserObject();
			m_selectMillComponentForConfig = (MillComponent)nodeInfo;

			edit_componentEditor();
		}

		if(nodeInfo instanceof MeasurePoint)
		{
			TreeNode nodeComponentContainer = node.getParent();
			DefaultMutableTreeNode nodeMill = (DefaultMutableTreeNode)nodeComponentContainer.getParent();
			DefaultMutableTreeNode nodeMillPark = (DefaultMutableTreeNode)nodeMill.getParent();

			m_selectedParkForConfig = (MillPark)nodeMillPark.getUserObject();
			m_selectedMillForConfig = (IMill)nodeMill.getUserObject();
			m_selectedMeasurePointForConfig = (MeasurePoint)nodeInfo;
			edit_mpointEditor();
		}

		if(nodeInfo instanceof String)
		{
			String temp = (String)nodeInfo;

			if(temp.compareTo("New Mill Park") == 0)
				new_millparkEditor();

			if(temp.compareTo("New Windmill") == 0)
			{
				m_selectedParkForConfig = (MillPark)((DefaultMutableTreeNode)node.getParent()).getUserObject();
				new_millEditor();

			}

			if(temp.compareTo("New Component") == 0)
			{
				TreeNode nodeComponentContainer = node.getParent();
				DefaultMutableTreeNode nodeMill = (DefaultMutableTreeNode)nodeComponentContainer.getParent();
				DefaultMutableTreeNode nodeMillPark = (DefaultMutableTreeNode)nodeMill.getParent();
				new_componentEditor();

			}

			if(temp.compareTo("New Measure Point") == 0)
			{
				TreeNode nodeComponentContainer = node.getParent();
				DefaultMutableTreeNode nodeMill = (DefaultMutableTreeNode)nodeComponentContainer.getParent();
				DefaultMutableTreeNode nodeMillPark = (DefaultMutableTreeNode)nodeMill.getParent();

				new_mpointEditor();

			}

		}
	}

	private void new_millparkEditor()
	{
		JLabel jLabel = new JLabel("Serial Number: ");
		JLabel jLabel1 = new JLabel("Location: ");

		JTextField jTextField = new JTextField();
		JTextField jTextField1 = new JTextField();

		JButton jButton = new JButton("Create");


		jLabel1.setBounds(new Rectangle(14, 45, 137, 16));
		jLabel.setBounds(new Rectangle(15, 15, 136, 16));
		jTextField.setBounds(new Rectangle(165, 15, 286, 20));
		jTextField1.setBounds(new Rectangle(165, 45, 286, 20));

		jButton.setBounds(new Rectangle(370, 75, 80, 25));

		frame.getConfigOption().add(jLabel);
		frame.getConfigOption().add(jLabel1);
		frame.getConfigOption().add(jTextField);
		frame.getConfigOption().add(jTextField1);
		frame.getConfigOption().add(jButton);

		jButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){

				int id = Integer.parseInt(((JTextField)frame.getConfigOption().getComponent(2)).getText());
				String location = ((JTextField)frame.getConfigOption().getComponent(3)).getText();

				m_model.CreateMillPark(id, location);

				updateConfigTree();
				updateParkList();
				frame.getConfigOption().removeAll();
				frame.getConfigOption().repaint();
			}
		});
	}

	private void edit_millparkEditor()
	{
		JLabel jLabel = new JLabel("Serial Number: ");
		JLabel jLabel1 = new JLabel("Location: ");
		JTextField jTextField = new JTextField(""+m_selectedParkForConfig.get_parkID());
		JTextField jTextField1 = new JTextField(m_selectedParkForConfig.get_location());
		JButton jButton = new JButton("Delete");

		jLabel.setBounds(new Rectangle(15, 15, 136, 16));
		jLabel1.setBounds(new Rectangle(14, 45, 137, 16));
		jTextField.setBounds(new Rectangle(165, 15, 286, 20));
		jTextField1.setBounds(new Rectangle(165, 45, 286, 20));
		jButton.setBounds(new Rectangle(370, 75, 80, 25));

		frame.getConfigOption().add(jLabel);
		frame.getConfigOption().add(jLabel1);
		frame.getConfigOption().add(jTextField);
		frame.getConfigOption().add(jTextField1);
		frame.getConfigOption().add(jButton);

		jButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				m_model.changeSelected(m_selectedParkForConfig);
				m_model.removeMillPark();

				updateConfigTree();
				updateParkList();
				frame.getConfigOption().removeAll();
				frame.getConfigOption().repaint();
			}
		});
	}

	private void new_millEditor()
	{
		JLabel jLabel = new JLabel("ID Number: ");
		JLabel jLabel1 = new JLabel("Type: ");

		JTextField jTextField = new JTextField();
		JComboBox jComboBox = new JComboBox(MillType.enumsToStringArray());

		JButton jButton = new JButton("Create");
		jLabel1.setBounds(new Rectangle(14, 45, 137, 16));
		jLabel.setBounds(new Rectangle(15, 15, 136, 16));
		jComboBox.setBounds(new Rectangle(165, 45, 286, 20));
		jTextField.setBounds(new Rectangle(165, 15, 286, 20));

		jButton.setBounds(new Rectangle(370, 104, 80, 25));

		frame.getConfigOption().add(jLabel);
		frame.getConfigOption().add(jLabel1);
		frame.getConfigOption().add(jComboBox);
		frame.getConfigOption().add(jTextField);

		frame.getConfigOption().add(jButton);


		jButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				m_model.changeSelected(m_selectedParkForConfig);
				int id = Integer.parseInt(((JTextField)frame.getConfigOption().getComponent(3)).getText());

				int index = ((JComboBox)frame.getConfigOption().getComponent(2)).getSelectedIndex();

				m_model.addMill(id, MillType.getMillType(index));

				updateConfigTree();
				updateParkList();
				frame.getConfigOption().removeAll();
				frame.getConfigOption().repaint();
			}
		});
	}

	private void edit_millEditor()
	{
		JLabel jLabel = new JLabel("Serial Number: ");
		JLabel jLabel1 = new JLabel("Type: ");
		JLabel jLabel2 = new JLabel("Height: ");
		JLabel jLabel3 = new JLabel("Wingspan: ");
		JTextField jTextField = new JTextField(""+m_selectedMillForConfig.getSerialNumber());
		JTextField jTextField1 = new JTextField(m_selectedMillForConfig.getType().toString());
		JTextField jTextField2 = new JTextField(""+m_selectedMillForConfig.getHeight());
		JTextField jTextField3 = new JTextField(""+m_selectedMillForConfig.getWingSpan());
		JButton jButton = new JButton("Delete");

		jLabel.setBounds(new Rectangle(15, 15, 136, 16));
		jLabel1.setBounds(new Rectangle(15, 45, 137, 16));
		jLabel2.setBounds(new Rectangle(15, 75, 136, 16));
		jLabel3.setBounds(new Rectangle(15, 105, 137, 16));

		jTextField.setBounds(new Rectangle(165, 15, 286, 20));
		jTextField1.setBounds(new Rectangle(165, 45, 286, 20));
		jTextField2.setBounds(new Rectangle(165, 75, 286, 20));
		jTextField3.setBounds(new Rectangle(165, 105, 286, 20));


		jButton.setBounds(new Rectangle(370, 135, 80, 25));

		frame.getConfigOption().add(jLabel);
		frame.getConfigOption().add(jLabel1);
		frame.getConfigOption().add(jLabel2);
		frame.getConfigOption().add(jLabel3);
		frame.getConfigOption().add(jTextField);
		frame.getConfigOption().add(jTextField1);
		frame.getConfigOption().add(jTextField2);
		frame.getConfigOption().add(jTextField3);
		frame.getConfigOption().add(jButton);

		jButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){

				m_model.changeSelected(m_selectedParkForConfig);
				m_model.removeMill(m_selectedMillForConfig);

				updateConfigTree();
				updateParkList();
				frame.getConfigOption().removeAll();
				frame.getConfigOption().repaint();
			}
		});
	}

	private void new_componentEditor()
	{

	}

	private void edit_componentEditor()
	{
		JButton jButton = new JButton("Delete");

		JLabel jLabel = new JLabel("Manufacture: ");
		JLabel jLabel1 = new JLabel("Commission Date: ");
		JTextField jTextField = new JTextField(m_selectMillComponentForConfig.get_manufacture());
		JTextField jTextField1 = new JTextField(m_selectMillComponentForConfig.get_commisionDate().toString());

		jLabel.setBounds(new Rectangle(15, 15, 136, 16));
		jLabel1.setBounds(new Rectangle(15, 45, 137, 16));

		jTextField.setBounds(new Rectangle(165, 15, 286, 20));
		jTextField1.setBounds(new Rectangle(165, 45, 286, 20));

		jButton.setBounds(new Rectangle(370, 135, 80, 25));

		frame.getConfigOption().add(jLabel);
		frame.getConfigOption().add(jLabel1);

		frame.getConfigOption().add(jTextField);
		frame.getConfigOption().add(jTextField1);

		frame.getConfigOption().add(jButton);

		if(m_selectMillComponentForConfig instanceof Gear)
		{
			JLabel jLabel2 = new JLabel("Number of Gears: ");
			JTextField jTextField2 = new JTextField(""+((Gear)m_selectMillComponentForConfig).get_numberOfGear());
			jLabel2.setBounds(new Rectangle(15, 75, 136, 16));
			jTextField2.setBounds(new Rectangle(165, 75, 286, 20));
			frame.getConfigOption().add(jLabel2);
			frame.getConfigOption().add(jTextField2);
		}

		if(m_selectMillComponentForConfig instanceof Computer)
		{
			JLabel jLabel2 = new JLabel("Number of cores: ");
			JTextField jTextField2 = new JTextField(""+((Computer)m_selectMillComponentForConfig).getM_coreNumber());
			jLabel2.setBounds(new Rectangle(15, 75, 136, 16));
			jTextField2.setBounds(new Rectangle(165, 75, 286, 20));
			frame.getConfigOption().add(jLabel2);
			frame.getConfigOption().add(jTextField2);
		}

		if(m_selectMillComponentForConfig instanceof Wing)
		{
			JLabel jLabel2 = new JLabel("Length: ");
			JLabel jLabel3 = new JLabel("Pitch angle: ");
			JTextField jTextField2 = new JTextField(""+((Wing)m_selectMillComponentForConfig).get_length());
			JTextField jTextField3 = new JTextField(""+((Wing)m_selectMillComponentForConfig).get_pitchAngle());
			jLabel2.setBounds(new Rectangle(15, 75, 136, 16));
			jLabel3.setBounds(new Rectangle(15, 105, 137, 16));
			jTextField2.setBounds(new Rectangle(165, 75, 286, 20));
			jTextField3.setBounds(new Rectangle(165, 105, 286, 20));
			frame.getConfigOption().add(jLabel2);
			frame.getConfigOption().add(jLabel3);
			frame.getConfigOption().add(jTextField2);
			frame.getConfigOption().add(jTextField3);
		}

		jButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){

				m_model.changeSelected(m_selectedParkForConfig);
				m_model.removeMillComponent(m_selectedMillForConfig, m_selectMillComponentForConfig);

				updateConfigTree();
				updateParkList();
				frame.getConfigOption().removeAll();
				frame.getConfigOption().repaint();
			}
		});
	}

	private void new_mpointEditor()
	{

	}

	private void edit_mpointEditor()
	{
		JButton jButton = new JButton("Delete");

		JLabel jLabel = new JLabel("Manufacture: ");
		JLabel jLabel1 = new JLabel("Commission Date: ");
		JTextField jTextField = new JTextField(m_selectedMeasurePointForConfig.get_manufacture());
		JTextField jTextField1 = new JTextField(m_selectedMeasurePointForConfig.getM_commisionDate().toString());

		jLabel.setBounds(new Rectangle(15, 15, 136, 16));
		jLabel1.setBounds(new Rectangle(15, 45, 137, 16));

		jTextField.setBounds(new Rectangle(165, 15, 286, 20));
		jTextField1.setBounds(new Rectangle(165, 45, 286, 20));

		jButton.setBounds(new Rectangle(370, 135, 80, 25));

		frame.getConfigOption().add(jLabel);
		frame.getConfigOption().add(jLabel1);

		frame.getConfigOption().add(jTextField);
		frame.getConfigOption().add(jTextField1);

		frame.getConfigOption().add(jButton);

		if(m_selectedMeasurePointForConfig instanceof AirTemperature)
		{
			JLabel jLabel2 = new JLabel("Scale: ");
			JTextField jTextField2 = new JTextField(""+((AirTemperature)m_selectedMeasurePointForConfig).get_scale());
			jLabel2.setBounds(new Rectangle(15, 75, 136, 16));
			jTextField2.setBounds(new Rectangle(165, 75, 286, 20));
			frame.getConfigOption().add(jLabel2);
			frame.getConfigOption().add(jTextField2);
		}

		jButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){

				m_model.changeSelected(m_selectedParkForConfig);
				m_model.removeMeasurePoint(m_selectedMillForConfig, m_selectedMeasurePointForConfig);

				updateConfigTree();
				updateParkList();
				frame.getConfigOption().removeAll();
				frame.getConfigOption().repaint();
			}
		});

	}

	@Override
	public void actionPerformed(ActionEvent arg0) {
		removeObserverToMill();

		frame.getBtnPauseResume().setEnabled(false);
		frame.getBtnStartStop().setEnabled(false);

		m_selectedPark = (MillPark)(frame.getCbMillParks().getSelectedItem());

		m_model.changeSelected(m_selectedPark);

		String text = m_selectedPark.toString();
		text += "\n Mills: " + m_selectedPark.getMills().size();
		frame.getTbParkInfo().setText(text);
		updateMainMillTable();
		addObserverToMill();
	}

	@Override
	public void valueChanged(ListSelectionEvent arg0) {
		int temp = frame.getTblMills().getSelectedRow();

		if(temp>=0)
			m_selectedIndex = temp; 

		try {
			frame.getTblMills().setRowSelectionInterval(m_selectedIndex, m_selectedIndex);	
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("Fejl!");
		}

		updateButtons();
	}



}
